import java.util.Date;

import grails.converters.JSON
import grails.util.Environment

import org.apache.commons.codec.digest.DigestUtils
import com.mastercard.*
import com.mastercard.auth.Role
import com.mastercard.auth.User
import com.mastercard.auth.User.Status;
import com.mastercard.common.utils.DateUtil;

class BootStrap {
//    def fixtureLoader
//    def searchableService

    def init = { servletContext ->
        def (adminRole, editorRole, customerRole) = setUpRoles()
        
        def admin = User.findByLogin("admin")
        if (!admin) {
            def password = Environment.current != Environment.PRODUCTION ? "changeit" : System.getProperty("initial.admin.password")
            if (!password) {
                throw new Exception("""
During the first run you must specify a password to use for the admin account. For example:

grails -Dinitial.admin.password=changeit run-app""")
            }
            else {
				Date now = new Date();
                admin = new User(login:"admin", email:"info@g2one.com",password:DigestUtils.sha256Hex(password),dateCreated:now, lastUpdated:now,lastUpdatedBy:"System", status:User.Status.LIVE )
                assert admin.email
                assert admin.addToRoles(adminRole)
                           .addToRoles(editorRole)
                           .addToRoles(customerRole)
                           .save(flush:true, failOnError: true)
            }
        }
        else if (!admin.roles) {
            admin.addToRoles(adminRole)
                 .addToRoles(editorRole)
                 .addToRoles(customerRole)
                 .save(flush:true, failOnError: true)
        }
        
        // Load dev data to make it easier to work on the application.
//        if ((System.getProperty("load.fixtures") || Environment.current == Environment.DEVELOPMENT) && User.count() < 2) {
//            println "Loading fixture data"
//            fixtureLoader.with {
//                load("users").load("plugins").load("tags", "ratings")
//                load("tutorials").load("tutorialTags")
//                load("wiki")
//                load("downloads")
//            }
//        }
        
        // We manually start the mirroring process to ensure that it comes after
        // Autobase performs its migrations.
//        if (Environment.current != Environment.DEVELOPMENT || System.getProperty("reindex")) {
//            println "Performing bulk index"
//            searchableService.reindex()
//        }
//        println "Starting mirror service"
//        searchableService.startMirroring()
		
		JSON.registerObjectMarshaller(User) {
			def returnArray = [:]
			returnArray['id'] = it.id
			returnArray['login'] = it.login
			if(it.email){
				returnArray['email'] = it.email
			}
			if(it.name){
				returnArray['name'] = it.name
			}
			if(it.mobile){
				returnArray['mobile'] = it.mobile
			}
			if(it.homePhone){
				returnArray['homePhone'] = it.homePhone
			}
			if(it.dateCreated){
				returnArray['dateCreated'] = DateUtil.formatDate(it.dateCreated)
			}
			if(it.lastUpdated){
				returnArray['lastUpdated'] = DateUtil.formatDate(it.lastUpdated)
			}
			if(it.lastUpdatedBy){
				returnArray['lastUpdatedBy'] = it.lastUpdatedBy
			}
			if(it.status){
				returnArray['status'] = it.status.toString()
			}
			if(it.creditCards){
				returnArray['creditCards'] = it.creditCards
			}
			if(it.categories){
				returnArray['categories'] = it.categories
			}
			if(it.addresses){
				returnArray['addresses'] = it.addresses
			}
			return returnArray
		}
		
		JSON.registerObjectMarshaller(CreditCard) {
			def returnArray = [:]
			returnArray['id'] = it.id
			returnArray['name'] = it.name
			returnArray['number'] = it.number
			if(it.expiryDate){
				returnArray['expiryDate'] = it.expiryDate
			}
			if(it.ccv2){
				returnArray['ccv2'] = it.ccv2
			}
			if(it.expiryDateStr){
				returnArray['expiryDateStr'] = it.expiryDateStr
			}
			returnArray['encryptNumber'] = it.encryptNumber
			if(it.bank){
				returnArray['bank'] = it.bank
			}
			if(it.transactions){
				returnArray['transactions'] = it.transactions
			}
			if(it.budgets){
				returnArray['budgets'] = it.budgets
			}
			return returnArray
		}
		
		JSON.registerObjectMarshaller(Bank) {
			def returnArray = [:]
			returnArray['id'] = it.id
			returnArray['name'] = it.name
			returnArray['country'] = it.country
			return returnArray
		}
    }

    def destroy = {
    }

    private setUpRoles() {
        // Admin role first. Adminstrator can access all parts of the application.
        def admin = Role.findByName(Role.ADMINISTRATOR) ?: new Role(name: Role.ADMINISTRATOR).save(failOnError: true)
        safelyAddPermission admin, "*"

        // Editor can edit pages, add screencasts, etc.
        def editor = Role.findByName(Role.EDITOR) ?: new Role(name: Role.EDITOR).save(failOnError: true)
        safelyAddPermission editor, "pluginTab:editWikiPage"
//        safelyAddPermission editor, "tutorial:create,edit,save,update"
//        safelyAddPermission editor, "webSite:create,edit,save,update"
//        safelyAddPermission editor, "likeDislike:like,dislike"

        // Observer: can't do anything that an anonymous user can't do.
        def observer = Role.findByName(Role.CUSTOMER) ?: new Role(name: Role.CUSTOMER).save(failOnError: true)

        return [admin, editor, observer]
    }

    private safelyAddPermission(entity, String permission) {
        if (!entity.permissions?.contains(permission)) {
            entity.addToPermissions permission
        }
    }
}
